package org.zdc.io;

/**
 * 
 * @author simple slime
 */

import haxe.macro.Expr;
#if neko
import neko.Lib;
#elseif cpp
import cpp.Lib;
#end
import sys.FileSystem;
import sys.io.File;
import haxe.Log;
using org.zdc.ZArray;
using Lambda;

class SimpleIO 
{
	public static inline var UNREADABLE = [
		"System Volume Information",
	];
	
	public function new() 
	{
		
	}
	
	/**
	 * walk a directory and call a function assigned each file or directory
	 * @param	path
	 * @param	fn
	 * @param	?layer
	 * @param	?type
	 */
	public static function walkDir(path:String, fn:ZPath->Void, ?layer:Int = 1, ?type:Int = ZPath.DIRECTORY):Void {
		var paths = readDir(path, layer, type).map(function(p:String):ZPath {
			return new ZPath(p);
		});
		for (p in paths) {
			Reflect.callMethod(null, fn, [p]);
		}
	}
	
	/**
	 * make a directory
	 * @param	path
	 */
	public static function mkdir(path:String):Void {
		var head = "";
		path = StringTools.trim(path);
		var dirs:Array<String> = ~/\\|\//gi.split(path);
		
		if (~/\S+:/gi.match(dirs[0])) {
			head = dirs.shift();
		}
		else {
			head = Sys.getCwd();
		}																//trace("dirs: " + dirs);
		for (i in 0...dirs.length) {
			var dir = head + "/" + dirs.slice(0, i + 1).join("/");		//trace(Std.format("FileSystem.exists(${dir})") + FileSystem.exists(dir));
			if (!FileSystem.exists(dir)) {								//trace("dir exists: " + dir);
				FileSystem.createDirectory(dir);
			}
		}
	}
	
	/**
	 * read directories or files in the path  
	 * @param	path			the path you would read
	 * @param	?layer			how much layer you will recur, 0 will recurse all directory
	 * @param	?type			the type of file you want
	 * @param	?curLayer		so assign any param, currently no idea to avoid this verbosity :P
	 * @return
	 */
	public static function readDir(path:String, ?layer:Int = 1, ?type:Int = ZPath.FILE_AND_DIRECTORY, ?curLayer:Int = 1):Array<String> {
		if (curLayer > layer) {
			return [];
		}
		var temp:Array<String> = [];	
		for (p in FileSystem.readDirectory(path)) {			 
			//windows下不可访问！
			if (UNREADABLE.indexOf(p) > -1) {				 
				continue;
			}
			p = path + "/" + p;								
			if (ZPath.isDirectory(p)) {		 				
				if (type == ZPath.DIRECTORY || type == ZPath.FILE_AND_DIRECTORY) {
					temp.push(p);
				}		
				if (layer > curLayer) {									 
					temp = temp.concat(readDir(p, layer, type, ++curLayer));
				}
			}
			else if (type == ZPath.FILE || type == ZPath.FILE_AND_DIRECTORY) {
				temp.push(p);
			}
		}
		return temp;
	}
	
}